// A popbumper for a pinball machine
//
// (c)2012 Felipe Sanches <fsanches@metamaquina.com.br>
// licensed under GPLv3 or later

metal_color = "silver";

module popbumper(game, version, cap_color="black", wafer_color="beige", hit_ring_height=35, playfield_thickness=15){
  translate([0,0,hit_ring_height + 2]) /*TODO: correct height*/
  popbumper_cap(game, version, cap_color);

  translate([0,0,hit_ring_height]) /*TODO: check the correct height of the hit_ring*/
  popbumper_hit_ring();

  popbumper_body();

  translate([0,0,3])
  color(wafer_color)
  popbumper_wafer();

  popbumper_spring();
  popbumper_spring_holder();
  popbumper_screws();

  translate([0,0, -playfield_thickness]){
    popbumper_mount_support();
    popbumper_solenoid();
  }
}

module popbumper_hit_ring(leg_length=77, ring_height=10){
  color(metal_color){
    render(){
      //legs
      for (i=[-1,1], $fn=20){
        translate([i*35/2, 0, -leg_length-ring_height])
        cylinder(r=5/2, h=leg_length);
      }

      translate([0, 0, -ring_height]){

        //ring
        difference($fn=40){
          cylinder(r1=46/2, r2=62/2, h=ring_height);
          translate([0, 0, -0.1])
          cylinder(r1=46/2-1, r2=62/2-1, h=ring_height+0.2);
        }

        //ring base
        linear_extrude(height=1, $fn=20)
        union(){
          difference(){
            circle(r=46/2);
            circle(r=46/2-2);
          }
          for (i=[-1,1]){
            translate([i*35/2, 0])
            circle(r=9/2);
          }
        }

      }
    }
  }
}

module popbumper_body(){
//TODO
}

module popbumper_wafer(){
  //WMS part no. 03-6035-XX (a.k.a. Bumper Wafer)
  $fn=60;
  stick_cone_length=11;
  stick_length=40.68;
  basedisc_height=2.2;
  basedisc_r1=29.7;
  basedisc_r2=21.3;

  render(){
    difference(){
      union(){
        //base disc
        cylinder(r1=basedisc_r1, r2=basedisc_r2, h=basedisc_height);

        //stick cone
        translate([0,0,-stick_cone_length])
        cylinder(r1=2.15,r2=5.05, h=stick_cone_length);

        //thin stick
        translate([0,0,-stick_length])
        cylinder(r1=1.6,r2=2.15, h=stick_length-stick_cone_length);

        //center
        cylinder(r=4.9,h=5.2);
      }

      //center holes
      translate([0,0,2.13])
      cylinder(r=2.54,h=10);

      translate([0,0,3.9])
      cylinder(r=3.25,h=10);

      //holes for hitring & lamp wiring
      for (step=[1:4]){
        rotate([0,0,45+step*90])
        translate([11,0,-1])
        cylinder(r=5.5,h=10);
      }

      //holes for screws
      for (step=[1:2]){
        rotate([0,0,step*180])
        translate([17.15,0,-1])
        cylinder(r=4.25,h=10);
      }
    }
  }
}

module popbumper_spring(){
//TODO
}

module popbumper_spring_holder(R=17.5, r=8, H=9.3,h=7){
  $fn=30;
  render(){
    rotate([0,0,45]){
      difference(){
        union(){
          cylinder(r=R, h=2);

          translate([0,0,2-H])
          cylinder(r=r, h=H);

          translate([11,0,0])
          cylinder(r=7/2, h=h);        

          translate([-11,0,0])
          cylinder(r=7/2, h=h);        
        }

        translate([0,0,4-H])
        cylinder(r=r-2, h=H);

        translate([0,0,-H])
        cylinder(r=r-3, h=H);

        translate([11,0,2])
        cylinder(r=7/2-1, h=h);        

        translate([-11,0,2])
        cylinder(r=7/2-1, h=h);        

        translate([11,0,-1])
        cylinder(r=3/2, h=h+2);        

        translate([-11,0,-1])
        cylinder(r=3/2, h=h+2);

        for(i=[1:4]){
          rotate([0,0,45+90*i])
          translate([R,0,-1])
          cylinder(r=4,h=4);
        }

        translate([0,11,-1])
        cylinder(r=5/2, h=4);        

        translate([0,-11,-1])
        cylinder(r=5/2, h=4);        

        translate([0,11,1])
        cylinder(r=9.3/2, h=4);

        translate([0,-11,1])
        cylinder(r=9.3/2, h=4);
      }
    }
  }
}

module popbumper_screws(){
//TODO
}

module popbumper_solenoid(){
//TODO
}

module popbumper_footprint(){
//2D footprint of the part
//TODO
}

module mount_holes_shape(){
  circle(r=4, $fn=40);

  for (i=[0,180]){
    rotate([0,0,i]){
      translate([17.5,0,0])
      circle(r=3.5, $fn=40);

      rotate([0,0,-45])
      translate([11.5,0,0])
      circle(r=2, $fn=40);
    }
  }

}

module popbumper_mount_holes(playfield_thickness=15){
//3D description of the cut to be made in the playfield wood
  r=8;
  H=9.3;

  translate([0,0,-playfield_thickness-1])
  linear_extrude(height=playfield_thickness+2)
  mount_holes_shape();

  translate([0,0,-H])
  cylinder(r=r, h=H+1, $fn=20);
}

//----------------------------------------------------
//pop bumper cap used in the Amiga version
// of the Party Land playfield

module partyland_msdos_popbumper_cap(cap_color="grey", R=75/2, r=43/2, H=10){
  border_thickness=2;
  d = 10;
  border=2;
  h = (r-border)*(r-border)/(2*d) - d/2;

  color(cap_color){
    difference(){
      union(){
        cylinder(r=R, h=border_thickness);
        translate([0,0,border_thickness])
        cylinder(r1=R, r2=r, h=H);
      }

      //TODO: spherical cut on top of the cap
      translate([0,0,H + h + border_thickness])
      sphere(r=h+d, $fn=80);
    }
  }
}

//----------------------------------------------------
//pop bumper cap used in the Amiga version
// of the Stones'n'Bones playfield

module star(r0=3, r1=5, n=5){
	union(){
		for (i=[1:n]){
			polygon([[0,0],
				[r0*cos(i * 360 / n), r0*sin(i * 360 / n)],
				[r1*cos(i * 360 / n - 180/n), r1*sin(i * 360 / n - 180/n)],
				[r0*cos((i-1) * 360 / n), r0*sin((i-1) * 360 / n)],
				[r0*cos(i * 360 / n), r0*sin(i * 360 / n)]]);
		}
	}
}

module stonesnbones_amiga_popbumper_cap(R=40, r=18, height=15){
	color([1,1,1])
	translate([0,0,0.4])
	intersection(){
		difference(){
			cylinder(h=height, r1=R, r2=r);
			cylinder(h=height+1, r=r);
		}
		linear_extrude(height=height+1)
		star(r0=r+5, r1=R-1, n=12);
	}

	color([0,0.6,0])
	difference(){
		cylinder(h=height, r1=R, r2=r);
		translate([0, 0, height-1])
		cylinder(h=10, r=r-2);
	}
}

//----------------------------------------------------
//pop bumper cap used in the MS-DOS version
// of the Stones'n'Bones playfield

module stonesnbones_msdos_popbumper_cap(R=40, r=18, height=15){
  h=5;

  module cap(){
	  difference(){
      scale([1,1,height/R])
		  sphere(r=R);
		  translate([0, 0, height])
      scale([1,1,h/r])
		  sphere(r=r);

      translate([-R, -R, -height])
      cube([2*R, 2*R, height]);
	  }
  }

	color([0.8,1,0.8])
	translate([0,0,0.4])
	intersection(){
		difference(){
      cap();
			cylinder(h=height, r=r);
		}
		linear_extrude(height=height+1)
		star(r0=r+5, r1=R-1, n=8);
	}

	color([0.7,0.5,0.7])
  cap();
}

//----------------------------------------------------
module popbumper_cap(game, version, capcolor){
  if (game=="stonesnbones"){
    if (version=="amiga")
      stonesnbones_amiga_popbumper_cap();

    if (version=="msdos")
      stonesnbones_msdos_popbumper_cap();
  }

  if (game=="partyland"){
    partyland_msdos_popbumper_cap(capcolor);
  }
}
//----------------------------------------------------

popbumper(game="partyland", version="msdos");
//popbumper(game="stonesnbones", version="msdos");
//popbumper(game="stonesnbones", version="amiga");

